#它是构建Dash应用的基础。Dash应用通常包含前端（HTML、CSS、JavaScript）和后端（Python）代码，
# 但Dash通过其特定的方式简化了这些组件的集成。
from dash import Dash
#request对象包含了客户端发来的请求信息，如URL、表单数据等；
# session对象用于存储用户的会话信息，它可以在用户的多个请求之间持久化数据。
from flask import request, session
#用于解析HTTP请求中用户代理字符串（User-Agent）的Python库。用户代理字符串是浏览器或其他HTTP客户端发送给服务器的一个标识，
# 它包含了关于客户端设备、操作系统、浏览器等信息。通过解析这些信息，开发者可以针对不同设备或浏览器做出适应性调整。
from user_agents import parse
#从config.env模块导入了AppConfig类
from config.env import AppConfig
#用于全局异常处理，即捕获应用中未处理的异常并进行相应的处理（如记录日志、发送错误通知、返回友好的错误页面等）
from config.exception import global_exception_handler
#logger通常是一个配置好的日志记录器（Logger），用于记录应用运行时的信息、警告、错误等。
# 这有助于开发者监控应用的运行状态，调试问题，或分析应用的行为。
from utils.log_util import logger


app = Dash(
    # 设置应用名称
    __name__,
    # 当设置为True时，
    # 这个选项会告诉Dash使用Flask的压缩功能来压缩发送到浏览器的响应。
    # 这有助于减少网络传输的数据量，从而提高应用的加载速度和性能。
    compress=True,
    #当设置为True时，这个选项会阻止Dash在回调（callback）函数中
    # 发生的异常被抛出到前端（即用户的浏览器）。默认情况下，
    # 如果回调函数中发生异常，Dash会将错误消息发送到浏览器，
    # 这可能会暴露敏感信息或给用户带来不好的体验。通过将此选项设置为True，
    # 你可以确保异常只在服务器端被记录和处理，
    # 而用户只会看到一个通用的错误消息或加载指示器。
    suppress_callback_exceptions=True,
    #这个参数通常用于指定当页面内容更新时，浏览器标签页的标题应该如何变化。
    # 在这个例子中，它被设置为None，意味着页面标题不会在内容更新时改变。
    # 如果你想要根据应用的状态来动态更新浏览器标签页的标题，
    # 你可以将这个函数设置为一个返回新标题的Python函数。
    update_title=None,
    #这个参数允许你指定一个全局的错误处理函数，
    # 该函数会在Dash应用中发生未捕获的异常时被调用。
    # 在这个例子中，它被设置为global_exception_handler，
    # 这意味着每当Dash应用遇到未捕获的异常时，
    # 都会调用global_exception_handler函数来处理这个异常。
    # 这个函数通常用于记录错误信息、发送警报或执行其他形式的错误恢复。
    on_error=global_exception_handler,
)
#这行代码从Dash应用中获取其底层的Flask服务器实例。
# 这允许你直接使用Flask的功能或与其他基于Flask的库集成。
server = app.server
# 设置应用标题
app.title = AppConfig.app_name

# 配置密钥
#用于Flask的会话管理和其他需要密钥的地方。
app.server.secret_key = AppConfig.app_secret_key
#这两个配置项用于调整压缩算法和压缩级别，但它们实际上是Flask-Compress（一个Flask扩展，用于压缩响应）的配置项，
# 而不是Dash或Flask本身的配置。如果你的项目中确实使用了Flask-Compress，这些配置会生效；否则，它们将被忽略。
app.server.config['COMPRESS_ALGORITHM'] = AppConfig.app_compress_algorithm
app.server.config['COMPRESS_BR_LEVEL'] = AppConfig.app_compress_br_level


# 获取用户浏览器信息
@server.before_request #是一个装饰器（decorator），它用于注册一个函数，该函数会在每次请求处理之前被自动调用。
def get_user_agent_info():
    # 获取请求地址
    # 如果是生产环境，则使用X-Forwarded-For头部信息，否则使用远程地址
    request_addr = (
        request.headers.get('X-Forwarded-For')
        if AppConfig.app_env == 'prod'
        else request.remote_addr
    )

    # 获取用户代理字符串
    user_string = str(request.user_agent)

    # 解析用户代理字符串
    user_agent = parse(user_string)

    # 获取浏览器名称
    bw = user_agent.browser.family

    # 如果浏览器版本信息不为空
    if user_agent.browser.version != ():
        bw_version = user_agent.browser.version[0]

        # 如果是IE浏览器
        if bw == 'IE':
            # 记录警告日志
            logger.warning(
                '[sys]请求人:{}||请求IP:{}||请求方法:{}||请求Data:{}',
                session.get('name'),
                request_addr,
                request.method,
                '用户使用IE内核',
            )
            # 返回提示信息，建议不使用IE浏览器或360浏览器兼容模式
            return "<h1 style='color: red'>请不要使用IE浏览器或360浏览器兼容模式</h1>"

        # 如果Chrome内核版本低于71
        if bw_version < 71:
            # 记录警告日志
            logger.warning(
                '[sys]请求人:{}||请求IP:{}||请求方法:{}||请求Data:{}',
                session.get('name'),
                request_addr,
                request.method,
                '用户Chrome内核版本太低',
            )
            # 返回提示信息，建议升级浏览器
            return (
                "<h1 style='color: red'>Chrome内核版本号太低，请升级浏览器</h1>"
                "<h1 style='color: red'><a href='https://www.google.cn/chrome/'>点击此处</a>可下载最新版Chrome浏览器</h1>"
            )


# 配置系统日志
# @server.after_request
# def get_callbacks_log(response):
#     logger.info("[sys]请求人:{}||请求IP:{}||请求方法:{}||请求Data:{}",
#                 session.get('name'), request.remote_addr, request.method, request.data.decode("utf-8"))
#
#     return response
